#include "MLTools_DistributionGenerator.h"

_MYLABLIB_BEGIN
CMLTools_DistributionGenerator::CMLTools_DistributionGenerator(void)
{
}

CMLTools_DistributionGenerator::~CMLTools_DistributionGenerator(void)
{
}

int CMLTools_DistributionGenerator::Initialize(int nNumBucket)
{
	m_nNumBucket = nNumBucket;
	return 0;
}

int CMLTools_DistributionGenerator::Generate(const CMLDataSet& dataSet, CMLDataSet& Probs)
{
	CMLDataPoint vMin;
	CMLDataPoint vMax;
	CMLDataPoint vBucketSize;
	int nRet;
	int i;
	int d;

	if (dataSet.Count() == 0)
		return 0;

	// Find the range of all dimension values
	nRet = FindRange(dataSet, vMin, vMax);
	ML_ON_FAILED_RETURN(nRet);

	// Calculate the bucke size of all dimensions
	vBucketSize = vMax;
	vBucketSize.sub(vMin);
	vBucketSize.div(m_nNumBucket);

	// Proprocess the Probs Matrix
	Probs.Resize(m_nNumBucket);
	CMLDataPoint initProb;
	initProb.resize(vMin.size());
	initProb.zero();
	for (i=0; i<m_nNumBucket; i++)
	{
		Probs.Set(i, initProb);
	}

	// Scan the dataset
	for (i=1; i<dataSet.Count(); i++)
	{
		const CMLDataPoint& p = dataSet.Get(i);
		for (d=0; d<p.size(); d++)
		{
			int nBucketIndex = (int)((p[d] - vMin[d]) / vBucketSize[d]);
			if (nBucketIndex == m_nNumBucket)
				nBucketIndex--;

			CMLDataPoint prob = Probs.Get(nBucketIndex);
			prob[d] += 1;
			Probs.Set(nBucketIndex, prob);
		}
	}

	return 0;
}

int CMLTools_DistributionGenerator::FindRange(const CMLDataSet &dataSet,  CMLDataPoint& min, CMLDataPoint& max)
{
	int i;
	int d;
	if (dataSet.Count() == 0)
		return -1;

	min = dataSet.Get(0);
	max = dataSet.Get(0);
	for (i=1; i<dataSet.Count(); i++)
	{
		const CMLDataPoint& p = dataSet.Get(i);
		for (d=0; d<p.size(); d++)
		{
			if (min[d] > p[d])
			{
				min[d] = p[d];
			}
			if (max[d] < p[d])
			{
				max[d] = p[d];
			}
		}
	}
	return 0;
}



_MYLABLIB_END
